using System;
using System.Xml;
using System.Text;
using System.Globalization;


namespace Waymex.Gps
{
	/// <summary>
	/// A collection of FlightBook objects.
	/// </summary>
	public class FlightBookCollection : System.Collections.IEnumerable
	{
		private const string vbModule = "FlightBooks";
		private const string XML_ROOT = "gpsflightbooks";
		private const string XML_FLIGHTBOOK = "gpsflightbook";
		private int m_hashCode = -1;

		private System.Collections.ArrayList mcFlightBooks;
		/// <summary>
		/// This method adds a FlightBook object to the collection. 
		/// </summary>
		public void Add(FlightBook flightBook)
		{

			try
			{
				mcFlightBooks.Add(flightBook);
			}
			catch (Exception e)
			{
				throw new InvalidDataException(e.Message, e);
			}
		}
		/// <summary>
		/// Returns the number of FlightBook objects in the collection. 
		/// </summary>
		public int Count
		{
			get
			{
				try
				{
					return mcFlightBooks.Count;
				}
				catch (Exception e)
				{
					throw new InvalidDataException(e.Message, e);
				}
			}
		}

		//default indexer property
		/// <summary>
		/// Can be used to refer to a member of the collection by ordinal reference.
		/// This Property is the default indexer in C#.
		/// </summary>
		public FlightBook this[int index]
		{
			get
			{
				return (FlightBook)mcFlightBooks[index];
			}

		}
		/// <summary>
		/// This method is the enumerator for the collection.
		/// </summary>
		public System.Collections.IEnumerator GetEnumerator()
		{
			return mcFlightBooks.GetEnumerator();
		}
		/// <summary>
		/// Constructor for the FlightBookCollection object.
		/// </summary>
		public FlightBookCollection() :  base()
		{
			mcFlightBooks = new System.Collections.ArrayList();
		}
        /// <summary>
        /// Returns an XML representation of the object.
        /// </summary>
        public string ToXml()
        {
            return ToXml(String.Empty);
        }
        /// <summary>
        /// Returns an XML representation of the object.
        /// This overloaded method accepts an xslt filename which can be used to ransform the xml.
        /// </summary>
        public string ToXml(string xsltFilename)
		{
			StringBuilder strbldXML = new StringBuilder("");
            String xml = String.Empty;

			try
			{
				strbldXML.Append ("<");
				strbldXML.Append (XML_ROOT);
				strbldXML.Append (">");

				foreach(FlightBook objFlightBook in mcFlightBooks)
				{
					strbldXML.Append(objFlightBook.ToXml());
				}

				strbldXML.Append ("</");
				strbldXML.Append (XML_ROOT);
				strbldXML.Append (">");

                //transform if required
                xml = strbldXML.ToString();

                if (xsltFilename.Length > 0)
                {
                    xml = Waymex.Xml.Transform.XsltTransform(xml, xsltFilename);
                }
            }
            catch (NullReferenceException e)
            { 
				throw new XmlException(e.Message, e);

			}
			return xml;
		}

		/// <summary>
		/// This method populates the object from XML.
		/// </summary>
        public void XmlLoad(string xml)
		{

			XmlDocument objDOM = new XmlDocument();

			try
			{
                objDOM.LoadXml(xml);

				if(objDOM.FirstChild.Name == XML_ROOT)
				{
					foreach(XmlNode objNode in objDOM.FirstChild.ChildNodes)
					{
						try
						{
							switch(objNode.Name)
							{
								case XML_FLIGHTBOOK:

									FlightBook objFlightBook = new FlightBook();
									objFlightBook.XmlLoad(objNode.OuterXml);
									mcFlightBooks.Add(objFlightBook);
									break;
							
							}
						}
						catch(NullReferenceException ex)
						{
						}
					}
				}	
			}
			catch(Exception e)
			{
				throw new XmlException(e.Message, e);
			}
		}
		/// <summary>
		/// This method returns a System.Data.Dataset populated with the contents of the FlightBookCollection object.
		/// The dataset includes one table called 'Flight Books'.
		///</summary>
		public System.Data.DataSet ToDataSet()
		{
			//constants for the dataset
			const string DS_FLIGHTBOOKS = "Flightbooks";

			//constants for the table
			const string DS_TABLE_FLIGHTBOOKS = "Flight Books";

			const string DS_FIELD_LAPS_TAKEOFF_TIME = "Takeoff Time";
			const string DS_FIELD_LAPS_TAKEOFF_TIME_TYPE = "System.Int32";
			const string DS_FIELD_LAPS_LANDING_TIME = "Landing Time";
			const string DS_FIELD_LAPS_LANDING_TIME_TYPE = "System.Int32";
			const string DS_FIELD_LAPS_TAKEOFF_LATTITUDE = "Takeoff Latitude";
			const string DS_FIELD_LAPS_TAKEOFF_LATTITUDE_TYPE = "System.Double";
			const string DS_FIELD_LAPS_TAKEOFF_LONGITUDE = "Takeoff Longitude";
			const string DS_FIELD_LAPS_TAKEOFF_LONGITUDE_TYPE = "System.Double";
			const string DS_FIELD_LAPS_LANDING_LATITUDE = "Landing Latitude";
			const string DS_FIELD_LAPS_LANDING_LATITUDE_TYPE = "System.Double";
			const string DS_FIELD_LAPS_LANDING_LONGITUDE = "Landing Longitude";
			const string DS_FIELD_LAPS_LANDING_LONGITUDE_TYPE = "System.Double";
			const string DS_FIELD_LAPS_NIGHT_TIME = "Night Time";
			const string DS_FIELD_LAPS_NIGHT_TIME_TYPE = "System.Int32";
			const string DS_FIELD_LAPS_NO_OFF_LANDINGS = "Number Of Landings";
			const string DS_FIELD_LAPS_NO_OFF_LANDINGS_TYPE = "System.Int32";
			const string DS_FIELD_LAPS_MAX_SPEED = "Maximum Speed";
			const string DS_FIELD_LAPS_MAX_SPEED_TYPE = "System.Single";
			const string DS_FIELD_LAPS_MAX_ALTITUDE = "Maximum Altitude";
			const string DS_FIELD_LAPS_MAX_ALTITUDE_TYPE = "System.Single";
			const string DS_FIELD_LAPS_DISTANCE = "Distance";
			const string DS_FIELD_LAPS_DISTANCE_TYPE = "System.Single";
			const string DS_FIELD_LAPS_CROSS_COUNTRY = "Cross Country";
			const string DS_FIELD_LAPS_CROSS_COUNTRY_TYPE = "System.Boolean";
			const string DS_FIELD_LAPS_DEP_NAME = "Departure Name";
			const string DS_FIELD_LAPS_DEP_NAME_TYPE = "System.String";
			const string DS_FIELD_LAPS_DEP_ID = "Departure Identity";
			const string DS_FIELD_LAPS_DEP_ID_TYPE = "System.String";
			const string DS_FIELD_LAPS_ARV_NAME = "Arrival Name";
			const string DS_FIELD_LAPS_ARV_NAME_TYPE = "System.String";
			const string DS_FIELD_LAPS_ARV_ID = "Arrival Identity";
			const string DS_FIELD_LAPS_ARV_ID_TYPE = "System.String";
			const string DS_FIELD_LAPS_AIRCRAFT_ID = "Aircraft ID";
			const string DS_FIELD_LAPS_AIRCRAFT_ID_TYPE = "System.String";


			//create a new data set
			System.Data.DataSet ds = new System.Data.DataSet(DS_FLIGHTBOOKS);
            ds.Locale = CultureInfo.InvariantCulture;
						
			//create the table			
			System.Data.DataTable dtF = new System.Data.DataTable(DS_TABLE_FLIGHTBOOKS);
            dtF.Locale = CultureInfo.InvariantCulture;

			//add the columns to the table
			dtF.Columns.Add(DS_FIELD_LAPS_TAKEOFF_TIME, Type.GetType(DS_FIELD_LAPS_TAKEOFF_TIME_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_LANDING_TIME, Type.GetType(DS_FIELD_LAPS_LANDING_TIME_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_TAKEOFF_LATTITUDE, Type.GetType(DS_FIELD_LAPS_TAKEOFF_LATTITUDE_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_TAKEOFF_LONGITUDE , Type.GetType(DS_FIELD_LAPS_TAKEOFF_LONGITUDE_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_LANDING_LATITUDE, Type.GetType(DS_FIELD_LAPS_LANDING_LATITUDE_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_LANDING_LONGITUDE, Type.GetType(DS_FIELD_LAPS_LANDING_LONGITUDE_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_NIGHT_TIME, Type.GetType(DS_FIELD_LAPS_NIGHT_TIME_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_NO_OFF_LANDINGS, Type.GetType(DS_FIELD_LAPS_NO_OFF_LANDINGS_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_MAX_SPEED, Type.GetType(DS_FIELD_LAPS_MAX_SPEED_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_MAX_ALTITUDE, Type.GetType(DS_FIELD_LAPS_MAX_ALTITUDE_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_DISTANCE, Type.GetType(DS_FIELD_LAPS_DISTANCE_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_CROSS_COUNTRY, Type.GetType(DS_FIELD_LAPS_CROSS_COUNTRY_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_DEP_NAME, Type.GetType(DS_FIELD_LAPS_DEP_NAME_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_DEP_ID, Type.GetType(DS_FIELD_LAPS_DEP_ID_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_ARV_NAME, Type.GetType(DS_FIELD_LAPS_ARV_NAME_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_ARV_ID, Type.GetType(DS_FIELD_LAPS_ARV_ID_TYPE));
			dtF.Columns.Add(DS_FIELD_LAPS_AIRCRAFT_ID, Type.GetType(DS_FIELD_LAPS_AIRCRAFT_ID_TYPE));

			//add the data
			foreach(FlightBook objFlightbook in mcFlightBooks)
			{
				object[] objRow = new object[17];
				objRow[0] = objFlightbook.TakeoffTime;
				objRow[1] = objFlightbook.LandingTime;
				objRow[2] = objFlightbook.TakeoffLatitude;
				objRow[3] = objFlightbook.TakeoffLongitude;
				objRow[4] = objFlightbook.LandingLatitude;
				objRow[5] = objFlightbook.LandingLongitude;
				objRow[6] = objFlightbook.NightTime;
				objRow[7] = objFlightbook.NumberOfLandings;
				objRow[8] = objFlightbook.MaximumSpeed;
				objRow[9] = objFlightbook.MaximumAltitude;
				objRow[10] = objFlightbook.Distance;
				objRow[11] = objFlightbook.CrossCountry;
				objRow[12] = objFlightbook.DepartureName;
				objRow[13] = objFlightbook.DepartureIdentity;
				objRow[14] = objFlightbook.ArrivalName;
				objRow[15] = objFlightbook.ArrivalIdentity;
				objRow[16] = objFlightbook.AircraftId;

				dtF.Rows.Add(objRow);
				
			}
			//tables populated so add the tables to the dataset
			ds.Tables.Add(dtF);

			return ds;
		}
        /// <summary>
        /// Overridden method. Returns true of the values of each
        /// of the properties are equal in value.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>boolean</returns>
        public override bool Equals(object obj)
		{
			try
			{
				FlightBookCollection objFlightBooks = null;

				//check the type first
				if(obj.GetType() != this.GetType() )
					return false;

				//type ok so cast
				objFlightBooks = (FlightBookCollection)obj;

				//if the number in each collection is different then exit
				int w1Count = mcFlightBooks.Count;
				int w2Count = objFlightBooks.Count;
				if(w1Count != w2Count)
					return false;

				//both with the same number of elements so chech each one in turn
				for( int index = 0; index < w1Count; index++ )
				{
					if( !objFlightBooks[index].Equals(mcFlightBooks[index]) )
						return false;
				}
			}
			catch
			{
				throw;
			}
			finally
			{}

			//if we got here then they must match
			return true;
		}
        /// <summary>
        /// Overridden function. Retrieves a value that indicates the hash code value for the object.
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
		{
			//this value will be used for the overriden GetHashCode function and should
			//ensure that two object that are the same return the same Hash Code.
			//the hash code has to be imutable to is stored in a member variable.
			if( m_hashCode <= 0 )
				m_hashCode = this.ToXml().GetHashCode();
	
			return m_hashCode;
		}

	}
}
